/* $Header: /roq/tiff/tif_aux.c 1     11/02/99 4:39p Zaphod $ */



/*

 * Copyright (c) 1991-1996 Sam Leffler

 * Copyright (c) 1991-1996 Silicon Graphics, Inc.

 *

 * Permission to use, copy, modify, distribute, and sell this software and 

 * its documentation for any purpose is hereby granted without fee, provided

 * that (i) the above copyright notices and this permission notice appear in

 * all copies of the software and related documentation, and (ii) the names of

 * Sam Leffler and Silicon Graphics may not be used in any advertising or

 * publicity relating to the software without the specific, prior written

 * permission of Sam Leffler and Silicon Graphics.

 * 

 * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 

 * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 

 * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  

 * 

 * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR

 * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,

 * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,

 * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 

 * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 

 * OF THIS SOFTWARE.

 */



/*

 * TIFF Library.

 *

 * Auxiliary Support Routines.

 */

#include "tiffiop.h"



#ifdef COLORIMETRY_SUPPORT

#include <math.h>



static void

TIFFDefaultTransferFunction(TIFFDirectory* td)

{

	uint16 **tf = td->td_transferfunction;

	long i, n = 1<<td->td_bitspersample;



	tf[0] = (uint16 *)_TIFFmalloc(n * sizeof (uint16));

	tf[0][0] = 0;

	for (i = 1; i < n; i++) {

		double t = (double)i/((double) n-1.);

		tf[0][i] = (uint16)floor(65535.*pow(t, 2.2) + .5);

	}

	if (td->td_samplesperpixel - td->td_extrasamples > 1) {

		tf[1] = (uint16 *)_TIFFmalloc(n * sizeof (uint16));

		_TIFFmemcpy(tf[1], tf[0], n * sizeof (uint16));

		tf[2] = (uint16 *)_TIFFmalloc(n * sizeof (uint16));

		_TIFFmemcpy(tf[2], tf[0], n * sizeof (uint16));

	}

}



static void

TIFFDefaultRefBlackWhite(TIFFDirectory* td)

{

	int i;



	td->td_refblackwhite = (float *)_TIFFmalloc(6*sizeof (float));

	for (i = 0; i < 3; i++) {

	    td->td_refblackwhite[2*i+0] = 0;

	    td->td_refblackwhite[2*i+1] = (float)((1L<<td->td_bitspersample)-1L);

	}

}

#endif



/*

 * Like TIFFGetField, but return any default

 * value if the tag is not present in the directory.

 *

 * NB:	We use the value in the directory, rather than

 *	explcit values so that defaults exist only one

 *	place in the library -- in TIFFDefaultDirectory.

 */

int

TIFFVGetFieldDefaulted(TIFF* tif, ttag_t tag, va_list ap)

{

	TIFFDirectory *td = &tif->tif_dir;



	if (TIFFVGetField(tif, tag, ap))

		return (1);

	switch (tag) {

	case TIFFTAG_SUBFILETYPE:

		*va_arg(ap, uint32 *) = td->td_subfiletype;

		return (1);

	case TIFFTAG_BITSPERSAMPLE:

		*va_arg(ap, uint16 *) = td->td_bitspersample;

		return (1);

	case TIFFTAG_THRESHHOLDING:

		*va_arg(ap, uint16 *) = td->td_threshholding;

		return (1);

	case TIFFTAG_FILLORDER:

		*va_arg(ap, uint16 *) = td->td_fillorder;

		return (1);

	case TIFFTAG_ORIENTATION:

		*va_arg(ap, uint16 *) = td->td_orientation;

		return (1);

	case TIFFTAG_SAMPLESPERPIXEL:

		*va_arg(ap, uint16 *) = td->td_samplesperpixel;

		return (1);

	case TIFFTAG_ROWSPERSTRIP:

		*va_arg(ap, uint32 *) = td->td_rowsperstrip;

		return (1);

	case TIFFTAG_MINSAMPLEVALUE:

		*va_arg(ap, uint16 *) = td->td_minsamplevalue;

		return (1);

	case TIFFTAG_MAXSAMPLEVALUE:

		*va_arg(ap, uint16 *) = td->td_maxsamplevalue;

		return (1);

	case TIFFTAG_PLANARCONFIG:

		*va_arg(ap, uint16 *) = td->td_planarconfig;

		return (1);

	case TIFFTAG_RESOLUTIONUNIT:

		*va_arg(ap, uint16 *) = td->td_resolutionunit;

		return (1);

#ifdef CMYK_SUPPORT

	case TIFFTAG_DOTRANGE:

		*va_arg(ap, uint16 *) = 0;

		*va_arg(ap, uint16 *) = (1<<td->td_bitspersample)-1;

		return (1);

	case TIFFTAG_INKSET:

		*va_arg(ap, uint16 *) = td->td_inkset;

		return (1);

#endif

	case TIFFTAG_EXTRASAMPLES:

		*va_arg(ap, uint16 *) = td->td_extrasamples;

		*va_arg(ap, uint16 **) = td->td_sampleinfo;

		return (1);

	case TIFFTAG_MATTEING:

		*va_arg(ap, uint16 *) =

		    (td->td_extrasamples == 1 &&

		     td->td_sampleinfo[0] == EXTRASAMPLE_ASSOCALPHA);

		return (1);

	case TIFFTAG_TILEDEPTH:

		*va_arg(ap, uint32 *) = td->td_tiledepth;

		return (1);

	case TIFFTAG_DATATYPE:

		*va_arg(ap, uint16 *) = td->td_sampleformat-1;

		return (1);

	case TIFFTAG_IMAGEDEPTH:

		*va_arg(ap, uint32 *) = td->td_imagedepth;

		return (1);

#ifdef YCBCR_SUPPORT

	case TIFFTAG_YCBCRCOEFFICIENTS:

		if (!td->td_ycbcrcoeffs) {

			td->td_ycbcrcoeffs = (float *)

			    _TIFFmalloc(3*sizeof (float));

			/* defaults are from CCIR Recommendation 601-1 */

			td->td_ycbcrcoeffs[0] = 0.299f;

			td->td_ycbcrcoeffs[1] = 0.587f;

			td->td_ycbcrcoeffs[2] = 0.114f;

		}

		*va_arg(ap, float **) = td->td_ycbcrcoeffs;

		return (1);

	case TIFFTAG_YCBCRSUBSAMPLING:

		*va_arg(ap, uint16 *) = td->td_ycbcrsubsampling[0];

		*va_arg(ap, uint16 *) = td->td_ycbcrsubsampling[1];

		return (1);

	case TIFFTAG_YCBCRPOSITIONING:

		*va_arg(ap, uint16 *) = td->td_ycbcrpositioning;

		return (1);

#endif

#ifdef COLORIMETRY_SUPPORT

	case TIFFTAG_TRANSFERFUNCTION:

		if (!td->td_transferfunction[0])

			TIFFDefaultTransferFunction(td);

		*va_arg(ap, uint16 **) = td->td_transferfunction[0];

		if (td->td_samplesperpixel - td->td_extrasamples > 1) {

			*va_arg(ap, uint16 **) = td->td_transferfunction[1];

			*va_arg(ap, uint16 **) = td->td_transferfunction[2];

		}

		return (1);

	case TIFFTAG_REFERENCEBLACKWHITE:

		if (!td->td_refblackwhite)

			TIFFDefaultRefBlackWhite(td);

		*va_arg(ap, float **) = td->td_refblackwhite;

		return (1);

#endif

	}

	return (0);

}



/*

 * Like TIFFGetField, but return any default

 * value if the tag is not present in the directory.

 */

int

TIFFGetFieldDefaulted(TIFF* tif, ttag_t tag, ...)

{

	int ok;

	va_list ap;



	va_start(ap, tag);

	ok =  TIFFVGetFieldDefaulted(tif, tag, ap);

	va_end(ap);

	return (ok);

}

